package com.sakura.probe.nosql.elasticsearch;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sakura.probe.common.api.CommonResult;
import com.sakura.probe.common.util.PageCalculate;
import com.sakura.probe.mapper.TopicCategoryMapper;
import com.sakura.probe.mapper.TopicMapper;
import com.sakura.probe.pojo.Topic;
import com.sakura.probe.pojo.TopicCategory;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class EsSearchServiceImpl implements EsSearchService {

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private TopicMapper topicMapper;

    @Autowired
    private TopicCategoryMapper topicCategoryMapper;

    @Override
    public int importAll() {
        List<Topic> list = topicMapper.selectList(null);
        Topic temp = null;
        List<TopicCategory> categoryList = topicCategoryMapper.selectList(null);
        HashMap<Long,String> map = new HashMap<>();
        for (TopicCategory category:categoryList){
            map.put(category.getTopicCategoryId(),category.getTopicCategoryName());
        }
        for (Topic topic:list){
            boolean d = deleteTopic(topic.getTopicId());
            if (!d){
                System.out.println("删除失败");
            }
            temp = new Topic(topic.getTopicId(),topic.getTopicCategoryId(),topic.getTopicName(),
                    topic.getEnableStatus(),topic.getLastEditTime(),map.get(topic.getTopicCategoryId()));
            boolean a = addTopic(temp);
            if (!a){
                System.out.println("添加失败");
            }
        }
        return 0;
    }

    @Override
    public boolean addTopic(Topic topic) {
        try {
            IndexRequest request = new IndexRequest(topic_index);
            request.id(String.valueOf(topic.getTopicId()));
            request.timeout("1s");
            //将发布的帖子内容放入Json中
            request.source(JSON.toJSONString(topic), XContentType.JSON);
            //客户端发送请求,获取相应的结果
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public CommonResult<List<Topic>> getTopicList(Topic topicCondition, int pageIndex, int pageSize) {
        SearchRequest searchRequest = new SearchRequest(topic_index);
        //构建查询条件
        SearchSourceBuilder sourceBuilder = addCondition(topicCondition.getTopicName(),pageIndex,pageSize);
        //执行搜索
        SearchResponse searchResponse = null;
        try {
            searchRequest.source(sourceBuilder);
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            return CommonResult.failed(e.getMessage());
        }
        //解析结果,并获取高亮信息
        ArrayList<Map<String,Object>> list = analysis(searchResponse.getHits().getHits());
        //ArrayList<Map<String,Object>转换成List<Topic>
        List<Topic> topicList = change(list);
        return CommonResult.success(topicList);
    }

    @Override
    public boolean updateTopic(long topicId,Map<String,Object> source) {
        try {
            UpdateRequest request = new UpdateRequest();
            UpdateRequest doc = request.doc(source);
            doc.index(topic_index);
            doc.id(""+topicId);
            UpdateResponse response = client.update(doc,RequestOptions.DEFAULT);
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    @Override
    public boolean deleteTopic(long TopicId) {
        try {
            DeleteRequest request = new DeleteRequest(topic_index);
            request.id(""+TopicId);
            DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    /**
     * 解析结果,并获取高亮信息
     * @param hits
     * @return
     */
    private ArrayList<Map<String, Object>> analysis(SearchHit[] hits) {
        ArrayList<Map<String,Object>> list = new ArrayList<>();
        for (SearchHit searchHit:hits){
            Map<String, HighlightField> highlightFieldMap = searchHit.getHighlightFields();
            //获取高亮的信息
            HighlightField property = highlightFieldMap.get("topicName");
            //原始的查询数据(没有高亮的)
            Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
            if (property!=null){
                Text[] fragments = property.fragments();
                String n_topicName = "";
                for (Text text:fragments){
                    n_topicName += text;
                }
                sourceAsMap.put("topicName",n_topicName);
            }
            list.add(sourceAsMap);
        }
        return list;

    }

    /**
     * 添加查询条件
     * @param topicName 要查询的关键字
     * @param pageIndex 页数
     * @param pageSize  一页显示的数量
     * @return
     */
    private SearchSourceBuilder addCondition(String topicName, int pageIndex, int pageSize) {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //查询条件(帖子的标题,并将标题进行ik分词器解析)
        //TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("TopicName",topicName);
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("topicName",topicName);
        sourceBuilder.query(matchQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        //将关键字进行高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置高亮的属性
        highlightBuilder.field("topicName");
        //自定义高亮样式
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);

        //分页
        sourceBuilder.size(pageSize);
        sourceBuilder.from(PageCalculate.calculateRowIndex(pageIndex,pageSize));
        return sourceBuilder;
    }

    /**
     * 将集合ArrayList<Map<String, Object>>转换成list<Topic>类型
     * @param list
     * @return
     */
    private List<Topic> change(ArrayList<Map<String, Object>> list) {
        List<Topic> result = null;
        try {
            //定义jackson数据转换操作类
            ObjectMapper mapper = new ObjectMapper();
            //将list集合转换成json格式
            String str = JSON.toJSONString(list);
            //指定要将str转换成的集合类型
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class,Topic.class);
            result = mapper.readValue(str,javaType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }



}
